#include <array_ref>

#include <assert.h>
#include <array>
#include <vector>

// Examples for array_ref's documentation.

//! [MyOldRoutine]
void MyOldRoutine(const int* elems, int N) {
  for (int i = 0; i < N; i++) { assert(elems[i] == N - i); }
}
//! [MyOldRoutine]

void OldRoutineCalls() {
//! [MyOldRoutine calls]
  std::vector<int> my_vector;
  for (size_t i = 5; i > 0; --i) { my_vector.push_back(i); }
  MyOldRoutine(my_vector.data(), my_vector.size());

  std::array<int, 4> my_std_array = {{4, 3, 2, 1}};
  MyOldRoutine(my_std_array.data(), my_std_array.size());

  int my_array[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
  MyOldRoutine(my_array, 10);

  int* dyn_array = new int[3];
  for (size_t i = 0; i < 3; ++i) { dyn_array[i] = 3 - i; }
  MyOldRoutine(dyn_array, 3);
//! [MyOldRoutine calls]
}

//! [MyNewRoutine]
void MyNewRoutine(std::array_ref<int> a) {
  for (size_t i = 0; i < a.size(); i++) { assert(a[i] == int(a.size() - i)); }
}
//! [MyNewRoutine]

void NewRoutineCalls() {
//! [MyNewRoutine calls]
  std::vector<int> my_vector;
  for (int i = 5; i > 0; --i) { my_vector.push_back(i); }
  MyNewRoutine(my_vector);

  std::array<int, 4> my_std_array = {{4, 3, 2, 1}};
  MyNewRoutine(my_std_array);

  int my_array[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
  MyNewRoutine(my_array);

  int* dyn_array = new int[3];
  for (size_t i = 0; i < 3; ++i) { dyn_array[i] = 3 - i; }
  MyNewRoutine(std::array_ref<int>(dyn_array, 3));
//! [MyNewRoutine calls]
}

void test_construction() {
  std::string s("Hello");
  std::array_ref<char> s_ref(s);
}

void test_make_array_ref() {
  std::vector<int> v;
  std::array_ref<int> ar = std::make_array_ref(v);
  int c_arr[] = {1, 2, 3};
  ar = std::make_array_ref(c_arr);
}

int main() {
  OldRoutineCalls();
  NewRoutineCalls();
  test_construction();
  test_make_array_ref();
}
